在前端開發中,記憶化(Memoization)主要用於優化性能,特別是在需要頻繁計算或重新渲染的情況下。所以我們今天來認識一下在Vue中,有幾種方式可以實現Memoization
目錄
- 介紹 記憶化
- 什麼時候才需要用記憶化
- Vue Memoization Example
-使用 computed
-使用 v-memo
-使用第三方套件- 延伸閱讀
記憶化是一種特定於算法和程式設計的優化技術。它用於儲存函數呼叫的結果,所以當同一個輸入再次出現時,可以直接從記憶儲存區取出結果,而不需要重新計算。
優點:
提高算法效能,特別是對於遞迴函數。
減少不必要的計算。
缺點:
會消耗額外的記憶體來儲存結果。
需要確保函數是「純函數(Pure Function)」,也就是相同的輸入必須產生相同的輸出。
記憶化(Memoization)是一種優化手段,不是所有情況都適用。以下是一些可能需要使用記憶化的情境:
在Vue中,有幾種方式可以實現Memoization
使用 computed 屬性
// vue3 Option Api寫法
computed: {
computedValue() {
// 進行一些昂貴的計算
return expensiveCalculation(this.someData);
}
}
// Vue3 Composition Api寫法
const computedValue = computed(()=>{ return expensiveCalculation(someData)})
詳細可看官方文件 v-memo
這邊舉例一個搭配 v-for 簡單範例
▼ 在這個例子中,v-memo接受[],其中條件是item.id === selected。v-memo用在這裡本質上是在說「只有當該項的被選中狀態改變時才需要更新」
<template>
<div>
<!-- 按鈕用於改變選中的項目 -->
<button @click="selectItem(1)">選擇項目 1</button>
<button @click="selectItem(2)">選擇項目 2</button>
<button @click="selectItem(3)">選擇項目 3</button>
<!-- 列表渲染 -->
<ul>
<li v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
<p>ID: {{ item.id }}</span> - <span>選中: {{ item.id === selected }}</p>
<p>{{ logRender(item.id) }}</p> // 測試是否渲染
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
// 列表數據
const list = [
{ id: 1, name: '項目 1' },
{ id: 2, name: '項目 2' },
{ id: 3, name: '項目 3' }
];
// 當前選中的項目 ID
const selected = ref(null);
// 函數用於改變選中的項目
const selectItem = (id) => {
selected.value = id;
};
// 用來測試是否渲染
const logRender = id => {
console.log(`Rendering item with ID: ${id}`);
return `Rendering item with ID: ${id}`;
};
</script>
✪ 當搭配v-for使用v-memo,確保兩者都綁定在同一個元素上。v-memo不能用在v-for內部。
功能大綱:先選擇2 > 在選擇1
Demo網址:https://hahasister-ironman-project.netlify.app/#/vmemo
使用v-memo
先選擇2,只有 ID 為 2的項目會被重新渲染,而其他項目則會保持不會
再選擇1,ID 為 2 和 3 的項目有變動才會被重新渲染
沒有用v-memo
不管是哪個選擇改變了,所有的項目都會被重新渲染
<li v-for="item in list" :key="item.id">
....
</li>
官方舉例是當v-for列表(長度超過1000 的情況),在處理大量數據或複雜操作時,使用 v-memo 的性能優勢會更為明顯
使用第三方套件
例如:useMemoize用途
清除緩存
getUser.clear() // 清除全部緩存
簡單範例
功能大綱
JSONPlaceholder: 一個免費的線上 REST API,你可以用它來獲取假數據。
網址:JSONPlaceholder
例如,https://jsonplaceholder.typicode.com/todos/1 能總是返回相同的待辦事項。
<template>
...
<div class="flex mt-4">
<button @click="getData(1)">獲取數據1</button>
<button @click="getData(2)">獲取數據2</button>
</div>
<div class="mt-4">
{{ data }}
</div>
...
</template>
<script setup>
import { ref } from 'vue';
import { useMemoize } from '@vueuse/core';
import axios from 'axios';
const data = ref(null);
const getUseMemoizeData = useMemoize(async id => {
const url = `https://jsonplaceholder.typicode.com/todos/${id}`;
const { data } = await axios.get(url);
return data;
});
const getData = async id => {
await getUseMemoizeData(id).then(res => {
data.value = res;
});
};
</script>
實務上我們可能會多次請求數據,如果請求數據資料都一樣的話,可以緩存就可以減少請求,所以我們來看看使用useMemoize的成果
Demo網址:https://hahasister-ironman-project.netlify.app/#/useMemoize
▲ 試著點擊「獲取數據1」> 再按「獲取數據1」因為得來值的一樣,所以不會再次請求 >按「獲取數據2」因為獲得的值不同,所以會再次請求
當然你也可以自己寫程式手動實現...
[演算法] Fibonacci:善用 cache 和 Memoization 提升程式效能
What is Memoization? How and When to Memoize in JavaScript and React
那我們明天再見了~